package com.cy.pj.sys.service.realm;

import com.cy.pj.sys.dao.SysMenuDao;
import com.cy.pj.sys.dao.SysRoleMenuDao;
import com.cy.pj.sys.dao.SysUserDao;
import com.cy.pj.sys.dao.SysUserRoleDao;
import com.cy.pj.sys.pojo.SysUser;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Component
public class ShiroUserRealm extends AuthorizingRealm {
    @Autowired
    SysUserDao sysUserDao;
    @Autowired
    private SysUserRoleDao sysUserRoleDao;
    @Autowired
    private SysRoleMenuDao sysRoleMenuDao;
    @Autowired
    private SysMenuDao sysMenuDao;


    /**
     * 通过此方法完成授权信息的获取及封装
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("权限控制");
        //1.获取登录用户信息，例如用户id
        SysUser user = (SysUser) principalCollection.getPrimaryPrincipal();
        Integer userId = user.getId();
        //2.基于用户id获取用户拥有的角色(sys_user_roles)
        List<Integer> roleIds =
                sysUserRoleDao.findRoleIdsByUserId(userId);
        if (roleIds == null || roleIds.size() == 0)
            throw new AuthorizationException();
        //3.基于角色id获取菜单id(sys_role_menus)
        List<Integer> menuIds =
                sysRoleMenuDao.findMenuIdsByRoleIds(roleIds);
        if (menuIds == null || menuIds.size() == 0)
            throw new AuthorizationException();
        //4.基于菜单id获取权限标识(sys_menus)
        List<String> permissions =
                sysMenuDao.findPermissions(menuIds);
        //5.对权限标识信息进行封装并返回
        Set<String> set = new HashSet<>();
        for (String per : permissions) {
            if (!StringUtils.isEmpty(per)) {
                set.add(per);
            }
        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(set);
        return info;//返回给授权管理器
    }

    /**
     * 通过此方法完成认证数据的获取及封装,系统
     * 底层会将认证数据传递认证管理器，由认证
     * 管理器完成认证操作。
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
            throws AuthenticationException {

        UsernamePasswordToken uToken = (UsernamePasswordToken)authenticationToken;
        String username = uToken.getUsername();
        SysUser user = sysUserDao.findUserByUserName(username);
        if (user==null) throw new UnknownAccountException();
        if (user.getValid()==0) throw new LockedAccountException();
        ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());

        return new SimpleAuthenticationInfo(user,user.getPassword(),credentialsSalt,getName());
    }

    //此方法中返回凭证加密对象，基于此对象对用户输入的密码进行加密操作
    @Override
    public CredentialsMatcher getCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");
        credentialsMatcher.setHashIterations(1);
        return credentialsMatcher;
    }

//    @Override
//    public void setCredentialsMatcher(
//            CredentialsMatcher credentialsMatcher) {
//        //构建凭证匹配对象
//        HashedCredentialsMatcher cMatcher=
//                new HashedCredentialsMatcher();
//        //设置加密算法
//        cMatcher.setHashAlgorithmName("MD5");
//        //设置加密次数
//        cMatcher.setHashIterations(1);
//        super.setCredentialsMatcher(cMatcher);
//    }
}
